package com.hyt.it.ogt.kq.main.controller.gov;

import com.hyt.it.ogt.kq.common.gov.annotation.ExamSys;
import com.hyt.it.ogt.kq.common.gov.constant.ResponseCode;
import com.hyt.it.ogt.kq.common.gov.constant.examsys.ActionEnum;
import com.hyt.it.ogt.kq.common.gov.constant.examsys.TypeEnum;
import com.hyt.it.ogt.kq.common.gov.constant.examsys.gce.GCEUploadConstant;
import com.hyt.it.ogt.kq.main.controller.base.BaseController;
import com.hyt.it.ogt.kq.service.gov.examsystem.ExamSystem;
import com.hyt.it.ogt.kq.service.gov.examsystem.ExamSystemFactory;
import com.hyt.it.ogt.kq.common.config.exception.KqException;
import com.hyt.it.ogt.kq.service.gov.model.param.OumaParam;
import com.hyt.it.ogt.kq.service.gov.service.ITaskConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiOperationSort;
import io.swagger.annotations.ApiSort;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * <p>
 * 考试系统接口
 * </p>
 *
 * @author huangyh
 * @since 2021-07-07
 */
@Slf4j
@Api(tags = "113.考试系统接口", value = "考试系统接口")
@ApiSort(value = 113)
@RestController
public class ExamSystemController extends BaseController {

    @Resource
    private ExamSystemFactory examSystemFactory;

    @Resource
    private ITaskConfigService iTaskConfigService;

    /**
     * 执行考试系统请求
     * @param request 请求
     * @param response 响应
     * @param type 考试系统大类
     * @param action action名称
     * @param taskCode 考试任务编号
     * @return 响应结果
     * @throws Exception 考务与考试系统其他异常
     */
    private String doAction(HttpServletRequest request, HttpServletResponse response,
                           String type, String action, String taskCode) throws Exception {
        String result = null;
        //获取考试系统实现
        ExamSystem examSystem = examSystemFactory.getExamSystem(type);
        switch (ActionEnum.getByName(action)) {
            //通过考点或考场编码查询考点或考场注册信息
            case GET_REGISTER_INFO:
                result = examSystem.getRegisterInfo(request, response, taskCode);
                break;
            //注册考场信息(GCE)
            case NEW_REGISTER_ROOM:
                result = examSystem.newRegisterRoom(request, response, taskCode);
                break;
            //注册考场信息(OBT)
            case REGISTER_ROOM:
                result = examSystem.registerRoom(request, response, taskCode);
                break;
            //获取已启用的考试项目列表
            case GET_EXAM_TASK_LIST:
                result = examSystem.getExamTaskList(request, response, taskCode);
                break;
            //根据考点编号得到其下的考试批次及考场信息
            case GET_TIME_BY_PLACE:
                result = examSystem.getTimeByPlace(request, response, taskCode);
                break;
            //下载测试项清单
            case GET_TEST_INVENTORY:
                result = examSystem.getTestInventory(request, response, taskCode);
                break;
            //更新下载模拟测试项清单结果
            case UPDATE_TEST_INVENTORY_STATE:
                result = examSystem.updateTestInventoryState(request, response, taskCode);
                break;
            //获取考场重考考务数据包
            case GET_RESIT_ROOM_PACKAGE:
                result = examSystem.getResitRoomPackage(request, response, taskCode);
                break;
            //重考考务包下载成功后更新重考考务包下载状态
            case UPDATE_RESIT_ROOM_PACKAGE_STATE:
                result = examSystem.updateResitRoomPackageState(request, response, taskCode);
                break;
            //下载基础包
            case GET_BASE_PACKAGE:
                result = examSystem.getBasePackage(request, response, taskCode);
                break;
            //更新基础包文件下载状态
            case UPDATE_BASE_DATA_STATE:
                result = examSystem.updateBaseDataState(request, response, taskCode);
                break;
            //获取已启用的考试项目编号
            case GET_TASK_CODE:
                result = examSystem.getTaskCode(request, response, taskCode);
                break;
            //获取考场考务数据包
            case GET_ROOM_PACKAGE:
                result = examSystem.getRoomPackage(request, response, taskCode);
                break;
            //考务包下载成功后更新考务包下载状态
            case UPDATE_ROOM_PACKAGE_STATE:
                result = examSystem.updateRoomPackageState(request, response, taskCode);
                break;
            //获取试卷包
            case GET_PAPER_DATA:
                result = examSystem.getPaperData(request, response, taskCode);
                break;
            //试卷包下载成功后更新试卷包下载状态
            case UPDATE_PAPER_DATA_STATE:
                result = examSystem.updatePaperDataState(request, response, taskCode);
                break;
            //获取试卷授权码
            case GET_PAPER_AUTHORIZATION_CODE:
                result = examSystem.getPaperAuthorizationCode(request, response, taskCode);
                break;
            //获取试卷授权码成功后通知考务更新试卷授权码状态
            case UPDATE_PAPER_AUTHORIZATION_CODE_STATE:
                result = examSystem.updatePaperAuthorizationCodeState(request, response, taskCode);
                break;
            //上传模拟测试报告
            case UPLOAD_TEST_REPORT:
                result = examSystem.uploadTestReport(request, response, taskCode);
                break;
            //同步考试数据包
            case EXAM_PACKAGE_SYNC:
                result = examSystem.examPackageSync(request, response, taskCode);
                break;
            //上传封场信息
            case UPDATE_CLOSURE:
                result = examSystem.updateClosure(request, response, taskCode);
                break;
            //获取上传监考机配置备份信息地址
            case GET_MONITOR_SETTING_BACKUP_PATH:
                result = examSystem.getMonitorSettingBackupPath(request, response, taskCode);
                break;
            //更新上传监考端配置备份信息状态
            case UPDATE_MONITOR_SETTING_BACKUP_STATE:
                result = examSystem.updateMonitorSettingBackupState(request, response, taskCode);
                break;
            //下载监考端配置备份信息
            case GET_MONITOR_SETTING:
                result = examSystem.getMonitorSettingBackup(request, response, taskCode);
                break;
            //更新下载监考端配置备份信息状态
            case UPDATE_MONITOR_SETTING_BACKUP_DOWNLOAD_STATE:
                result = examSystem.updateMonitorSettingBackupDownloadState(request, response, taskCode);
                break;
            //测试考试系统能否正常连接考务系统
            case CHECK_EXAM_SYSTEM_CONNECTION:
                result = examSystem.checkExamSystemConnection(request, response, taskCode);
                break;
            //获取服务器时间
            case GET_SERVER_TIME:
                result = examSystem.getServerTime(request, response, taskCode);
                break;
            //获取考生信息(在线添加考生)
            case GET_CANDIDATE_INFO:
                result = examSystem.getCandidateInfo(request, response, taskCode);
                break;
            //校验是否可以上传考试结果，并获取上传路径
            case GET_RESULT_UPLOAD_PATH:
                result = examSystem.getResultUploadPath(request, response, taskCode);
                break;
            //校验考试结果是否上传成功
            case VERIFY_RESULT:
                result = examSystem.verifyResult(request, response, taskCode);
                break;
            //上传考试结果成功后通知考务更新上传状态
            case UPDATE_RESULT_STATE:
                result = examSystem.updateResultState(request, response, taskCode);
                break;
            //上报考场考试过程操作数据状态
            case UPDATE_EXAM_MONITOR:
                result = examSystem.updateExamMonitor(request, response, taskCode);
                break;
            case POST_BEHAVIOR_ANALYSIS:
                result = examSystem.postBehaviorAnalysis(request, response, taskCode);
                break;
            case UPDATE_BACKUP_STATE:
                result = examSystem.updateBackUpState(request, response, taskCode);
                break;
            //获取华为云OBS信息
            case GET_HUAWEI_CLOUD_OBS_INFO:
                result = examSystem.getHuaweiCloudObsInfo();
                break;
        }
        return result;
    }

    /**
     * 处理考试系统请求
     * @param request 请求
     * @param response 响应
     * @param taskCode 考试任务编号
     * @return 响应结果
     */
    private String action(HttpServletRequest request, HttpServletResponse response, String taskCode) {
        //考务接口返回结果
        String result;
        try {
            // 获取考试系统类型(后续需要优化为从缓存中获取)
            String type = iTaskConfigService.getExamSystemTypeByTaskCode(taskCode);
            //获取请求Action名称
            String action = request.getParameter(ActionEnum.ACTION.getName());
            //请求考务接口
            result = this.doAction(request, response, type, action, taskCode);
        } catch (KqException k) {
            //政企考务业务异常
            if (ResponseCode.EXAMINATION_EXAM_SYSTEM_BUSINESS_EXCEPTION.getCode().equals(k.getErrCode())) {
                //返回XML或JSON等字符串的返回结果
                result = k.getMessage();
                return result;
            }
            //返回数字的返回结果
            result = String.valueOf(k.getErrCode());
            return result;
        } catch (Exception e) {
            //考务与考试系统其他异常
            log.error("考务与考试系统其他异常: ", e);
            return null;
        }
        return result;
    }

    @ApiOperation(
            value = "13.1 考务请求",
            notes = "考试系统的考务请求"
    )
    @ApiOperationSort(value = 1)
    @ExamSys("考务请求")
    @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, value = "{taskCode}/Sys/HttpInterface.aspx")
    public String examinationAction(HttpServletRequest request, HttpServletResponse response, @PathVariable String taskCode) {
        return this.action(request, response, taskCode);
    }

    @ApiOperation(
            value = "13.6 异地备份工具请求",
            notes = "异地备份工具请求"
    )
    @ApiOperationSort(value = 6)
    @ExamSys("异地备份请求")
    @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, value = "{taskCode}/sys/httpInterface.aspx")
    public String backUpAction(HttpServletRequest request, HttpServletResponse response, @PathVariable String taskCode) {
        return this.action(request, response, taskCode);
    }

    @ApiOperation(
            value = "13.2 GCE考点请求",
            notes = "GCE考试系统的考点请求"
    )
    @ApiOperationSort(value = 2)
    @ExamSys("GCE考点请求")
    @RequestMapping(method = {RequestMethod.GET, RequestMethod.POST}, value = "{taskCode}/HTTP.aspx")
    public String gcePlaceAction(HttpServletRequest request, HttpServletResponse response, @PathVariable String taskCode) {
        return this.action(request, response, taskCode);
    }

    @ApiOperation(
            value = "13.3 OBT考点请求",
            notes = "OBT考试系统的考点请求"
    )
    @ApiOperationSort(value = 3)
    @ExamSys("OBT考点请求")
    @PostMapping("{taskCode}/Http.aspx")
    public String obtPlaceAction(HttpServletRequest request, HttpServletResponse response, @PathVariable String taskCode) {
        return this.action(request, response, taskCode);
    }

    @ApiOperation(
            value = "13.4 获取山大欧玛考试配置(OBT专用)",
            notes = "获取山大欧玛考试配置(OBT专用)"
    )
    @ApiOperationSort(value = 4)
    @GetMapping("{taskCode}/api/dtface.ashx")
    public String getOumaExaminationConfig(OumaParam oumaParam, @PathVariable String taskCode) {
        //获取考试系统实现
        ExamSystem examSystem = examSystemFactory.getExamSystem(TypeEnum.OBT.toString());
        return examSystem.getOumaExaminationConfig(oumaParam);
    }

    @ApiOperation(
            value = "13.5 考试文件包上传(GCE专用)",
            notes = "考试文件包上传(GCE专用)"
    )
    @ApiOperationSort(value = 5)
    @PostMapping("{taskCode}" + GCEUploadConstant.DIRECTORY_SEPARATOR +
            GCEUploadConstant.INTERFACE_NAME + GCEUploadConstant.DIRECTORY_SEPARATOR +
            "{type}" + GCEUploadConstant.DIRECTORY_SEPARATOR + "{roomCode}")
    public String gceUpload(HttpServletRequest request, HttpServletResponse response, MultipartFile fileName,
                            @PathVariable String taskCode, @PathVariable String type, @PathVariable String roomCode) {
        //获取时间戳
        long timestamp = System.currentTimeMillis();
        //获取考试系统实现
        ExamSystem examSystem = examSystemFactory.getExamSystem(TypeEnum.GCE.toString());
        //上传文件包
        return examSystem.upload(timestamp, request, response, fileName, taskCode, type, roomCode);
    }

}
